<?php
namespace common\widgets\webuploader;

/**
 * 
 * 资源文件管理库（含文件上传、资源解析等...）
 *
 */
class WebUploaderUtil {
    
    //上传文件存放路径
    static function getFilePath(){
        return '/'.WebUploaderConst::FILE;
    }
    
    //文件临时存放路径
    static function getTempPath(){
        return '/'.WebUploaderConst::TEMP;
    }
    
    //-------------上传Action开始-----------------------------------------------------------------------------------------
    
    //获取上传控件的组建列表
    static function getComponentList($model,$field){
        
        $behavior = self::getBehavior($model);
        
        $list = self::getPostVal($model, $field);
        if(empty($list)){
            return array();
        }
        
        $listStr = $behavior->attribute.',';
        
        $arr = array();
        foreach ($list as $val){
            if(self::contain($listStr, $val.',')){
                $arr[] = $val;
            }
        }
        
        return array_unique($arr);
        
    }
    
    //获取上传控件的参数值
    static function getPostVal($model,$field){
        
        $val = \Yii::$app->request->post($field);
        if(!empty($val)){
            return $val;
        }
        
        $val = \Yii::$app->request->post($model->formName())[$field];
        return $val;
        
    }
    
    //获得上传组件的行为对象
    static function getBehavior($model){
        $behaviors = $model->behaviors();
        
        $uploaderBehavior = null;
        foreach ($behaviors as $key=>$behavior){
            if(isset($behavior['class']) && $behavior['class'] == UploaderBehavior::className()){
                $uploaderBehavior = $model->getBehavior($key);
                break;
            }
        }
        return $uploaderBehavior;
    }
    
    //获取model在[afterInsert或afterUpdate]之后的对应上传组件的老数据
    static function getOldVal($model,$field){
        
        $uploaderBehavior = self::getBehavior($model);
        if(empty($uploaderBehavior)){
            return '';
        }
        
        $val = $uploaderBehavior->oldAttributeList["old_{$field}"];
        return $val;
    }
    
    /**
     * 上传单个图片，afterInsert事件会调用
     */
    static function uploadSingleImage($model,$field){
        
        $fileText = self::getOldVal($model, $field);	//资源临时地址
        $width = self::getPostVal($model, $field.'_width'); //图片资源宽度
        $height = self::getPostVal($model, $field.'_height'); //图片资源高度
        
        if($width != 0 && $height != 0){    //如果同时含有[宽度] & [高度] ,则先对临时地址进行剪切
            self::img2thumb(".".$fileText, ".".$fileText,$width,$height,1);
        }
        self::remove2ProductPath($fileText,1);  //图片文件 移动 到正式地址
        
    }
    
    /**
     * 上传单个文件，afterInsert事件会调用
     */
    static function uploadSingleFile($model,$field){
    
        $fileText = self::getOldVal($model, $field);	//资源临时地址
        self::remove2ProductPath($fileText,0);
    
    }
    
    /**
     * 上传多个图片，afterInsert事件会调用
     */
    static function uploadMultiImage($model,$field){
        self::removeMulti2ProductPath($model,$field,1);
    }
    
    /**
     * 上传多个文件，afterInsert事件会调用
     */
    static function uploadMultiFile($model,$field){
        self::removeMulti2ProductPath($model, $field,0);
    }
    
    //-------------上传Action结束⇧⇧⇧⇧⇧⇧⇧⇧-----------------------------------------------------------------------------------------
    
    
    //-------------更新Action开始-----------------------------------------------------------------------------------------
    
    /**
     * 更新单个图片，afterUpdate事件会调用
     */
    static function updateSingleImage($model,$field) {
        
        $oldText = self::getOldVal($model, $field);	//旧数据
        $fileText = $model->$field;	//资源临时地址
        $width = self::getPostVal($model, $field.'_width'); //图片资源宽度
        $height = self::getPostVal($model, $field.'_height'); //图片资源高度
        
        $fileText = str_replace(self::getFilePath(),self::getTempPath(),$fileText);  //因为在beforeUpdate的时候，已经把$model->$field的值全部替换成正式环境下的值，所以如果要转移，还得转换成为临时地址
        if($width != 0 && $height != 0){    //如果同时含有[宽度] & [高度] ,则先对临时地址进行剪切
            self::img2thumb(".".$fileText, ".".$fileText,$width,$height,1);
        }
        
        self::deleteAndRemoveSingel2ProductPath($oldText, $fileText,1);
        
    }
    
    /**
     * 更新单个文件，用于更新Action
     */
    static function updateSingleFile($model,$field) {
        
        $oldText = self::getOldVal($model, $field); //旧数据
        $fileText = $model->$field;	//资源临时地址
        self::deleteAndRemoveSingel2ProductPath($oldText, $fileText,0);
    
    }
    
    /**
     * 更新多个图片，用于更新Action
     */
    static function updateMultiImage($model,$field) {
        self::deleteAndRemoveMulti2ProductPath($model, $field,1);
    }
    
    /**
     * 更新多个文件，用于更新Action
     */
    static function updateMultiFile($model,$field) {
        self::deleteAndRemoveMulti2ProductPath($model, $field,0);
    }
    
    //-------------更新Action结束⇧⇧⇧⇧⇧⇧⇧⇧-----------------------------------------------------------------------------------------
    
    
    //-------------删除Action开始-----------------------------------------------------------------------------------------
    
    /**
     * 删除[单图]，用于删除Action
     */
    public static function deleteSingleImage($text) {
        self::deleteFileRes($text,1);
    }
    
    /**
     * 删除[单文件]，用于删除Action
     */
    public static function deleteSingleFile($text) {
        self::deleteFileRes($text,0);
    }
    
    /**
     * 删除[多图]，用于删除Action
     */
    public static function deleteMultiImage($text) {
        self::deleteMultiFileRes($text,1);
    }
    
    /**
     * 删除[多文件]，用于删除Action
     */
    public static function deleteMultiFile($text) {
        self::deleteMultiFileRes($text,0);
    }
    
    //-------------删除Action结束⇧⇧⇧⇧⇧⇧⇧⇧-----------------------------------------------------------------------------------------
    
    
	/**
	 * 获取资源文件列表
	 */
	static function getFileList($str){
		if(empty($str)){
			return array();
		}
		return explode(WebUploaderConst::EXPLODE_CHAR, $str); 
	}
	
	/**
	 * 删除文件
	 * @param $filepath 文件路径，如'/uploads/file/xx.gif' 或 '/uploads/file/22.doc:成语大全'
	 * @param $isImgUploadOnly 是否仅仅是图片上传组建？
	 */
	static function deleteFileRes($filepath,$isImgUploadOnly=1){
		if(empty($filepath)){
			return true;
		}
		if($isImgUploadOnly != 1){
			$arr = explode(':', $filepath);
			$filepath = $arr[0];
		}
		if(!self::contain($filepath, "./")){
		    $filepath = ".".$filepath;
		}
		if(file_exists($filepath)){
			return unlink(iconv("UTF-8","gb2312",$filepath));	//支持中文文件名删除
		}
	}
	
	/**
	 * 将临时（单）文件转移到正式环境中
	 * @param $tempfilepath 文件临时地址，如'/uploads/temp/1.jpg'或'/uploads/temp/2.doc:成语大全'
	 * @param $isImgUploadOnly	是否仅仅是图片组建上传方式？
	 */
	static function remove2ProductPath($tempfilepath,$isImgUploadOnly=1){
		
	    if(empty($tempfilepath)){
	        return ;
	    }
	    
	    if($isImgUploadOnly != 1){
			$arr = explode(':', $tempfilepath);
			$tempfilepath = $arr[0];
		}
		$productPath = self::getRemovedProductPath($tempfilepath);
		if(file_exists(".".$tempfilepath)){	//文件存在，则执行下步操作...
			copy(".".$tempfilepath,".".$productPath); //拷贝到正式目录
			self::deleteFileRes($tempfilepath,1);	//删除临时文件
		}
	}
	
	/**
	 * 获取（单）文件转移到正式环境中的路径
	 */
	static function getRemovedProductPath($tempfilepath){
		$productPath = str_replace("/temp/", "/file/", $tempfilepath);
		return $productPath;
	}
	
	/**
	 * 将临时（多）文件转移到正式环境中
	 * @param $isImgUploadOnly 是否仅仅是图片上传组建方式？
	 */
	static function removeMulti2ProductPath($model,$field,$isImgUploadOnly=1){
	    
	    $fileText = self::getOldVal($model, $field);	//资源临时地址
	    $width = self::getPostVal($model, $field.'_width');	//宽度
	    $height = self::getPostVal($model, $field.'_height');	//高度
	    
	    $arr = self::getFileList($fileText);
	    foreach ($arr as $fileVal){
	         
	        if($width != 0 && $height != 0 && $isImgUploadOnly==1){    //如果同时含有[宽度] & [高度] ,则先对临时地址进行剪切
	            self::img2thumb(".".$fileVal, ".".$fileVal,$width,$height,1);
	        }
	        self::remove2ProductPath($fileVal,$isImgUploadOnly);
	    }
		
	}
	
	/**
	 * 获取（多）文件转移到正式环境中的路径
	 */
	static function getRemovedMultiProductPath($text){
	
		$list = self::getFileList($text);
		$newText = '';
		$index = 0;
		foreach ($list as $fileAddr){
			if(empty($fileAddr)){
				continue;
			}
			if($index != 0){
				$newText .= WebUploaderConst::EXPLODE_CHAR;
			}
			$newText .= self::getRemovedProductPath($fileAddr);
			$index++;
		}
		return $newText;
	}
	
	/**
	 * 删除（单）文件中废弃部分，新增的转移到正式环境中
	 * @param $isImgUploadOnly 是否仅仅是图片上传组建方式？
	 */
	static function deleteAndRemoveSingel2ProductPath($oldText,$newText,$isImgUploadOnly=1) {
		
	    if(empty($oldText) && empty($newText)){
	        return ;
	    }
	    
		$imgAddr = self::getRemovedProductPath($newText);	//获取到缩略图正式环境下的地址
		
		if($isImgUploadOnly != 1){
			$arr = explode(':', $imgAddr);
			$arr2 = explode(':', $oldText);
			$imgAddr = $arr[0];
			$oldText = $arr2[0];
		}
		if($oldText != $imgAddr){
			if(!empty($oldText)){
				self::deleteFileRes($oldText,$isImgUploadOnly);
			}
			if(!empty($newText)){
			    $newText = str_replace(self::getFilePath(),self::getTempPath(),$newText);  //因为在beforeUpdate的时候，已经把$model->$field的值全部替换成正式环境下的值，所以如果要转移，还得转换成为临时地址
			    self::remove2ProductPath($newText,$isImgUploadOnly);
			}
		}
	
	}
	
	/**
	 * 删除（多）文件中废弃部分，新增的转移到正式环境中
	 * @param $isImgUploadOnly 是否仅仅是图片上传组建方式？
	 */
	static function deleteAndRemoveMulti2ProductPath($model,$field,$isImgUploadOnly=1) {
		
	    $oldText = self::getOldVal($model, $field);
	    $newText = $model->$field;	//新的临时地址
	    
	    $width = self::getPostVal($model, $field.'_width'); //图片资源宽度
	    $height = self::getPostVal($model, $field.'_height'); //图片资源高度
	    
	    //多文件操作，删除前一任的文件，再进行转移临时文件
	    $oldImgList = self::getFileList($oldText); //上一任的多文件地址
	    $newImgList = self::getFileList($newText); //最新多文件地址
	     
	    //1....删除废弃的文件地址（如果不包含，则正则在新文本内容中该文件已被废弃，进行删除操作）
	    $newText .= WebUploaderConst::EXPLODE_CHAR;
	    foreach($oldImgList as $oldFile) {
	    
	        $oldFileTmp = $oldFile.WebUploaderConst::EXPLODE_CHAR;
	        if($isImgUploadOnly != 1){
	            $arr = explode(':', $oldFile);
	            $oldFile = $arr[0];
	            $oldFileTmp = $oldFile.':';
	        }
	    
	        if(!self::contain($newText, $oldFileTmp)) {
	            self::deleteFileRes($oldFile,1);
	        }
	    }
	    
	    
	    //2....将临时地址转入到正式目录
	    $oldText .= WebUploaderConst::EXPLODE_CHAR;
	    foreach($newImgList as $newFile) {
	         
	        $newFileTmp = $newFile.WebUploaderConst::EXPLODE_CHAR;
	        if($isImgUploadOnly != 1){
	            $arr = explode(':', $newFile);
	            $newFile = $arr[0];
	            $newFileTmp = $newFile.':';
	        }
	         
	        if(!self::contain($oldText, $newFileTmp)) {
	            
	            $newFile = str_replace(self::getFilePath(),self::getTempPath(),$newFile);  //因为在beforeUpdate的时候，已经把$model->$field的值全部替换成正式环境下的值，所以如果要转移，还得转换成为临时地址
	            if($width != 0 && $height != 0 && $isImgUploadOnly == 1){    //如果同时含有[宽度] & [高度] ,则先对临时地址进行剪切
	                self::img2thumb(".".$newFile, ".".$newFile,$width,$height,1);
	            }
	            self::remove2ProductPath($newFile,$isImgUploadOnly);
	        }
	    }
	    
	    
	}
	
	/**
	 * 将多文件地址删除【供删除事务用途】
	 * @param $isImgUploadOnly 是否仅仅是图片上传组建方式？
	 */
	public static function deleteMultiFileRes($text,$isImgUploadOnly=1) {
		if(empty($text)){
			return;
		}
		$fileList = self::getFileList($text);
		//删除废弃的文件地址
		foreach($fileList as $fileAddr){
			self::deleteFileRes($fileAddr,$isImgUploadOnly);
		}
	}
	
	
	/**
	 * 获取文件后缀
	 * @param $filestr：文件整体路径
	 * 返回：文件后缀
	 */
	static function getExtendName($filestr){
	    $gonten= explode('.',$filestr);
	    $gonten = array_reverse($gonten);
	    return strtolower($gonten[0]);
	}
	
	/**
	 * 判断[$str4source字符串]是否包含[$str4search字符串]，不区别大小写
	 * @param $str4source	大单位
	 * @param $str4search	小单位
	 * 返回 true 或 false
	 */
	static function contain($str4source,$str4search){
	    $index = strripos($str4source,$str4search);
	    if($index === false){
	        return false;
	    }else{
	        return true;
	    }
	}
	
	/**
	 * 生成缩略图(强大的PHP生成缩略图函数。)
	 * @author yangzhiguo0903@163.com
	 * @param string     源图绝对完整地址{带文件名及后缀名}
	 * @param string     目标图绝对完整地址{带文件名及后缀名}
	 * @param int        缩略图宽{0:此时目标高度不能为0，目标宽度为源图宽*(目标高度/源图高)}
	 * @param int        缩略图高{0:此时目标宽度不能为0，目标高度为源图高*(目标宽度/源图宽)}
	 * @param int        是否裁切{宽,高必须非0}
	 * @param int/float  缩放{0:不缩放, 0<this<1:缩放到相应比例(此时宽高限制和裁切均失效)}
	 * @return boolean
	 */
	static function img2thumb($src_img, $dst_img, $width = 75, $height = 75, $cut = 0, $proportion = 0){
	    if(!is_file($src_img)){
	        return false;
	    }
	    $ot = pathinfo($dst_img, PATHINFO_EXTENSION);
	    $otfunc = 'image' . ($ot == 'jpg' ? 'jpeg' : $ot);
	    $srcinfo = getimagesize($src_img);
	    $src_w = $srcinfo[0];
	    $src_h = $srcinfo[1];
	    $type  = strtolower(substr(image_type_to_extension($srcinfo[2]), 1));
	    $createfun = 'imagecreatefrom' . ($type == 'jpg' ? 'jpeg' : $type);
	
	    $dst_h = $height;
	    $dst_w = $width;
	    $x = $y = 0;
	
	    /**
	     * 缩略图不超过源图尺寸（前提是宽或高只有一个）
	     */
	    if(($width> $src_w && $height> $src_h) || ($height> $src_h && $width == 0) || ($width> $src_w && $height == 0)){
	        $proportion = 1;
	    }
	    if($width> $src_w){
	        $dst_w = $width = $src_w;
	    }
	    if($height> $src_h){
	        $dst_h = $height = $src_h;
	    }
	
	    if(!$width && !$height && !$proportion){
	        return false;
	    }
	    if(!$proportion){
	        if($cut == 0){
	            if($dst_w && $dst_h){
	                if($dst_w/$src_w> $dst_h/$src_h){
	                    $dst_w = $src_w * ($dst_h / $src_h);
	                    $x = 0 - ($dst_w - $width) / 2;
	                }else{
	                    $dst_h = $src_h * ($dst_w / $src_w);
	                    $y = 0 - ($dst_h - $height) / 2;
	                }
	            }else if($dst_w xor $dst_h){
	                if($dst_w && !$dst_h){	//有宽无高
	                    $propor = $dst_w / $src_w;
	                    $height = $dst_h  = $src_h * $propor;
	                }else if(!$dst_w && $dst_h){	//有高无宽
	                    $propor = $dst_h / $src_h;
	                    $width  = $dst_w = $src_w * $propor;
	                }
	            }
	        }else{
	            if(!$dst_h){	//裁剪时无高
	                $height = $dst_h = $dst_w;
	            }
	            if(!$dst_w){	//裁剪时无宽
	                $width = $dst_w = $dst_h;
	            }
	            $propor = min(max($dst_w / $src_w, $dst_h / $src_h), 1);
	            $dst_w = (int)round($src_w * $propor);
	            $dst_h = (int)round($src_h * $propor);
	            //$x = ($width - $dst_w) / 2;
	            //$y = ($height - $dst_h) / 2;
	            $x = 0;
	            $y = 0;
	        }
	    }else{
	        $proportion = min($proportion, 1);
	        $height = $dst_h = $src_h * $proportion;
	        $width  = $dst_w = $src_w * $proportion;
	    }
	
	    $src = $createfun($src_img);
	    $dst = imagecreatetruecolor($width ? $width : $dst_w, $height ? $height : $dst_h);
	    $white = imagecolorallocate($dst, 255, 255, 255);
	    imagefill($dst, 0, 0, $white);
	
	    if(function_exists('imagecopyresampled')){
	        imagecopyresampled($dst, $src, $x, $y, 0, 0, $dst_w, $dst_h, $src_w, $src_h);
	    }else{
	        imagecopyresized($dst, $src, $x, $y, 0, 0, $dst_w, $dst_h, $src_w, $src_h);
	    }
	    $otfunc($dst, $dst_img);
	    imagedestroy($dst);
	    imagedestroy($src);
	    return true;
	}
	
	
}